﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#include "CThreadManager.h"

namespace UX_STL
{
namespace UXTypesExt
{

#ifdef _UXS_STL_CONFIGURATION_H
	CThreadManager *	_s_pThreadMan	= null;
#endif


/*
=================================================
	конструктор
=================================================
*/
	CThreadManager::CThreadManager(): _uThreadCounter(0)
	{
#	ifdef _UXS_STL_CONFIGURATION_H
		ASSERT( _s_pThreadMan == null );
		_s_pThreadMan = this;
#	endif
	}
	
/*
=================================================
	деструктор
=================================================
*/
	CThreadManager::~CThreadManager()
	{
		DestroyAll();

#	ifdef _UXS_STL_CONFIGURATION_H
		ASSERT( _s_pThreadMan == this );
		_s_pThreadMan = null;
#	endif
	}
	
/*
=================================================
	добавить поток в список
=================================================
*/
	void CThreadManager::AddThread(IThread *pThread)
	{
		RemoveThread( pThread );

		SCOPELOCK( _sLockThreads.GetScopeWriteLock() );
		_aThreads.PushBack( pThread );

		pThread->_uThreadID = ++_uThreadCounter;
	}

/*
=================================================
	удалить поток из списка
=================================================
*/
	void CThreadManager::RemoveThread(IThread *pThread)
	{
		SCOPELOCK( _sLockThreads.GetScopeWriteLock() );

		FOR( i, _aThreads ) {
			if ( pThread == _aThreads[i] ) {
				_aThreads.FastErase( i );
				return;
			}
		}
	}

/*
=================================================
	завершить все потоки
=================================================
*/
	void CThreadManager::DestroyAll()
	{
		{
			SCOPELOCK( _sLockThreads.GetScopeReadLock() );

			FOR( i, _aThreads ) {
				_aThreads[i]->Exit();
			}
		}

		SCOPELOCK( _sLockThreads.GetScopeWriteLock() );
		_aThreads.Clear();
	}
	
/*
=================================================
	приостановить все потоки
=================================================
*/
	bool CThreadManager::PauseAll()
	{
		SCOPELOCK( _sLockThreads.GetScopeReadLock() );

		FOR( i, _aThreads ) {
			_aThreads[i]->Pause();
		}
		return true;
	}
	
/*
=================================================
	возобновить все потоки
=================================================
*/
	bool CThreadManager::ResumeAll()
	{
		SCOPELOCK( _sLockThreads.GetScopeReadLock() );
		
		FOR( i, _aThreads ) {
			_aThreads[i]->Resume();
		}
		return true;
	}
	
/*
=================================================
	возвращает количество потоков
=================================================
*/
	usize CThreadManager::GetCount()
	{
		SCOPELOCK( _sLockThreads.GetScopeReadLock() );
		return _aThreads.Count();
	}

/*
=================================================
	проверяет является ли текущий поток
	одним из созданных потоков в этом объекте движка
=================================================
*/
	bool CThreadManager::IsCurProcessThread()
	{
		bool	ret = true;
		
		SCOPELOCK( _sLockThreads.GetScopeReadLock() );
		
		FOR( i, _aThreads ) {
			ret &= _aThreads[i]->IsCurrent();
		}
		return ret;
	}
	
/*
=================================================
	добавляет операцию в свободный поток
=================================================
*/
	bool CThreadManager::PushOp(e_thread::type eType, IThreadOp *pOp, bool bHightPriority, bool bExceptCurrent)
	{
		IThread	*p_th	= null;
		usize	 u_rate	= -1;
		
		SCOPELOCK( _sLockThreads.GetScopeReadLock() );

		FOR( i, _aThreads )
		{
			if ( (!bExceptCurrent || THREAD() != _aThreads[i]) and
				 EnumCmpE( _aThreads[i]->ThreadType(), eType ) and
				 _aThreads[i]->EmploymentRate() < u_rate )
			{
				p_th	= _aThreads[i];
				u_rate	= _aThreads[i]->EmploymentRate();
			}
		}

		if ( p_th != null )
			return p_th->Push( pOp, bHightPriority );
		else
			return false;
	}
	
/*
=================================================
	добавляет операцию во все потоки заданного типа,
	кроме текущего
=================================================
*/
	bool CThreadManager::PushOpToAll(e_thread::type eType, IThreadOpC *pOp, bool bHightPriority, bool bExceptCurrent)
	{
		bool	b_res		= true;
		uint	u_counter	= 0;
		
		SCOPELOCK( _sLockThreads.GetScopeReadLock() );
		
		FOR( i, _aThreads )
		{
			if ( (!bExceptCurrent || THREAD() != _aThreads[i]) and
				 EnumCmpE( _aThreads[i]->ThreadType(), eType ) )
			{
				++u_counter;
			}
		}

		if ( u_counter == 0 ) {
			pOp->Free();
			return false;
		}

		pOp->SetCounter( u_counter );
		
		FOR( i, _aThreads )
		{
			if ( (!bExceptCurrent || THREAD() != _aThreads[i]) and
				 EnumCmpE( _aThreads[i]->ThreadType(), eType ) )
			{
				b_res &= _aThreads[i]->Push( pOp, bHightPriority );
			}
		}

		return b_res;
	}

//-------------------------------------------------------------------

}	// UXTypesExt
}	// UX_STL